import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class SingletonLazy {
    private volatile static SingletonLazy instance = null;
    public static SingletonLazy getInstance() {
        if(instance == null) {
            synchronized(SingletonLazy.class) {
                if(instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
    private SingletonLazy() {}
}

class MyBlockingQueue {
    private String[] elems = null;
    private int head = 0;
    private int tail = 0;
    private int size = 0;
    Object locker = new Object();
    public MyBlockingQueue(int capacity) {
        elems = new String[capacity];
    }

    public void put(String elem) throws InterruptedException {
        synchronized (locker) {
            while(size >= elems.length) {
                //队列满了,阻塞等待
                locker.wait();
            }
            elems[tail] = elem;
            tail++;
            if(tail >= elems.length) {
                tail = 0;
            }
            size++;
            locker.notify();
        }
    }

    public String take() throws InterruptedException {
        String ret = null;
        synchronized (locker) {
            while(size == 0) {
                //队列为空, 阻塞等待
                locker.wait();
            }
            ret = elems[head];
            head++;
            if(head >= elems.length) {
                head = 0;
            }
            size--;
            locker.notify();
        }
        return ret;
    }
}

class MyTimerTask implements Comparable<MyTimerTask> {
    private long time;
    //实际任务要执行的代码
    private Runnable runnable;

    public long getTime() {
        return time;
    }

    public MyTimerTask(Runnable runnable, long delay) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

    public void run() {
        runnable.run();
    }


    @Override
    public int compareTo(MyTimerTask o) {
        return (int)(this.time - o.time);
    }
}

class MyTimer {
    //负责扫描任务的队列
    private Thread t = null;
    //任务队列
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<MyTimerTask>();

    private Object locker = new Object();

    public void shedule(Runnable runnable, long delay) {
        synchronized (locker) {
            MyTimerTask task = new MyTimerTask(runnable,delay);
            queue.offer(task);
            //添加新的元素后,就可以唤醒扫描线程的wait()了
            locker.notify();
        }
    }

    //构造方法, 创建扫描线程, 让扫描线程来完成判断和执行
    public MyTimer() {
        t = new Thread(()->{
            while(true) {
                try {
                    synchronized (locker) {
                        while(queue.isEmpty()) {
                            locker.wait();
                        }
                        MyTimerTask task = queue.peek();
                        long curTime = System.currentTimeMillis();
                        if(curTime >= task.getTime()) {
                            queue.poll();
                            task.run();
                        } else {
                            locker.wait(task.getTime()-curTime);
                        }
                    }
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t.start();
    }
}

class MyThreadPoolExecutor1 {
    private final List<Thread> threadList = new ArrayList<>();
    private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);
    //n来指定创建多少线程
    public MyThreadPoolExecutor1(int n) {
        for(int i = 0 ;i < n; i++) {
            Thread t = new Thread(()->{
                //线程要做的事情是把任务队列中的任务不停的取出来,并且去执行
                while(true) {
                    try {
                        Runnable runnable = queue.take();
                        runnable.run();
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            t.start();
            threadList.add(t);
        }
    }
    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }
}

class MyThreadPoolExecutor {
    private List<Thread> list = new ArrayList<>();
    private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);

    public MyThreadPoolExecutor(int n) {
        for(int i = 0; i<n; i++) {
            Thread t = new Thread(()->{
                while(true) {
                    Runnable task = null;
                    try {
                        task = queue.take();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    task.run();
                }
            });
            t.start();
            list.add(t);
        }
    }

    public void submit(Runnable task) throws InterruptedException {
        queue.put(task);
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPoolExecutor executor = new MyThreadPoolExecutor(4);
        for (int i = 0; i < 1000; i++) {
            int n = i;
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("执行任务" + n + ",当前线程为:" + Thread.currentThread().getName());
                }
            });
        }
    }
}

class Test1 {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(4);
        service.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });

    }

    public static void main3(String[] args) {
        MyTimer timer = new MyTimer();
        timer.shedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 3000");
            }
        },3000);

        timer.shedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 2000");
            }
        },2000);

        timer.shedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 1000");
            }
        },1000);

        System.out.println("hello main");
    }
    public static void main2(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello 3000");
            }
        },3000);

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello 2000");
            }
        },2000);

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello 1000");
            }
        },1000);

        System.out.println("hello main");
    }

    public static void main1(String[] args) {
        MyBlockingQueue myBlockingQueue = new MyBlockingQueue(1000);
        Thread t1 = new Thread(()->{
            int n = 1;
            while(true) {
                try {
                    myBlockingQueue.put(n+"");
                    System.out.println("生产元素: " + n);
                    Thread.sleep(1000);
                    n++;
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        Thread t2 = new Thread(()->{
            while(true) {
                try {
                    String n = myBlockingQueue.take();
                    System.out.println("消费元素: " + n);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        t1.start();
        t2.start();
    }
}
